import express from 'express';
import { Request, Response } from 'express';
import winston from 'winston';
import { EmailOrchestrator } from '../services/EmailOrchestrator';
import { EmailTrackingService } from '../services/EmailTrackingService';
import { EmailPreferenceService } from '../services/EmailPreferenceService';
import { EmailComplianceService } from '../services/EmailComplianceService';
import { authMiddleware } from '../middleware/auth';
import { emailConfig } from '../config/emailConfig';

const router = express.Router();

// Initialize services (these would typically be dependency injected)
let emailOrchestrator: EmailOrchestrator;
let trackingService: EmailTrackingService;
let preferenceService: EmailPreferenceService;
let complianceService: EmailComplianceService;

// Initialize email system
const initializeEmailSystem = async () => {
  try {
    emailOrchestrator = new EmailOrchestrator(emailConfig.system);
    await emailOrchestrator.start();
    
    // Individual services for specific endpoints
    trackingService = new EmailTrackingService(
      emailConfig.system.supabase.url,
      emailConfig.system.supabase.key,
      winston.createLogger({ level: 'info' })
    );
    
    preferenceService = new EmailPreferenceService(
      emailConfig.system.supabase.url,
      emailConfig.system.supabase.key,
      winston.createLogger({ level: 'info' })
    );
    
    complianceService = new EmailComplianceService(
      emailConfig.system.supabase.url,
      emailConfig.system.supabase.key,
      winston.createLogger({ level: 'info' })
    );
    
    console.log('Email system initialized successfully');
  } catch (error) {
    console.error('Failed to initialize email system:', error);
    throw error;
  }
};

// Initialize on module load
initializeEmailSystem();

/**
 * @route POST /api/email/subscribe
 * @desc Subscribe user to email notifications
 * @access Public
 */
router.post('/subscribe', async (req: Request, res: Response) => {
  try {
    const {
      userId,
      email,
      preferences = {},
      source = 'web',
      campaign
    } = req.body;

    if (!userId || !email) {
      return res.status(400).json({
        success: false,
        error: 'userId and email are required'
      });
    }

    const result = await emailOrchestrator.subscribeUser(
      userId,
      email,
      preferences,
      {
        source,
        ipAddress: req.ip,
        userAgent: req.get('User-Agent'),
        campaign
      }
    );

    if (result.requiresConfirmation) {
      // Send double opt-in confirmation email
      await emailOrchestrator.sendImmediateEmail(
        userId,
        'subscription_confirmation',
        {
          confirmationUrl: `${emailConfig.system.baseUrl}/confirm/${result.confirmationToken}`
        }
      );
    }

    res.json({
      success: result.success,
      message: result.requiresConfirmation 
        ? 'Confirmation email sent. Please check your inbox.'
        : 'Successfully subscribed to email notifications.',
      requiresConfirmation: result.requiresConfirmation
    });

  } catch (error) {
    console.error('Subscribe error:', error);
    res.status(500).json({
      success: false,
      error: 'Internal server error'
    });
  }
});

/**
 * @route POST /api/email/unsubscribe
 * @desc Unsubscribe user from email notifications
 * @access Public
 */
router.post('/unsubscribe', async (req: Request, res: Response) => {
  try {
    const { userId, token, reasons } = req.body;

    let result;
    
    if (token) {
      // Process unsubscribe via token (from email link)
      result = await complianceService.processUnsubscribeToken(token, reasons);
    } else if (userId) {
      // Process unsubscribe via user ID (from dashboard)
      result = await emailOrchestrator.unsubscribeUser(userId, 'web_form', reasons);
    } else {
      return res.status(400).json({
        success: false,
        error: 'Either userId or token is required'
      });
    }

    if (result.success) {
      // Send unsubscribe confirmation email
      if (result.userId) {
        await emailOrchestrator.sendImmediateEmail(
          result.userId,
          'unsubscribe_confirmation',
          {},
          { skipCompliance: true }
        );
      }
    }

    res.json({
      success: result.success,
      message: result.success 
        ? 'You have been successfully unsubscribed.'
        : result.error,
      email: result.email
    });

  } catch (error) {
    console.error('Unsubscribe error:', error);
    res.status(500).json({
      success: false,
      error: 'Internal server error'
    });
  }
});

/**
 * @route GET /api/email/confirm/:token
 * @desc Confirm double opt-in subscription
 * @access Public
 */
router.get('/confirm/:token', async (req: Request, res: Response) => {
  try {
    const { token } = req.params;

    const result = await complianceService.confirmOptIn(token);

    if (result.success && result.userId) {
      // Start welcome series
      await emailOrchestrator.sendImmediateEmail(
        result.userId,
        'welcome_series_1',
        {},
        { priority: 'high' }
      );

      res.redirect(`${emailConfig.system.baseUrl}/welcome?confirmed=true`);
    } else {
      res.redirect(`${emailConfig.system.baseUrl}/error?type=confirmation&message=${encodeURIComponent(result.error || 'Invalid token')}`);
    }

  } catch (error) {
    console.error('Confirmation error:', error);
    res.redirect(`${emailConfig.system.baseUrl}/error?type=system&message=Internal+error`);
  }
});

/**
 * @route GET /api/email/preferences/:userId
 * @desc Get user email preferences
 * @access Private
 */
router.get('/preferences/:userId', authMiddleware, async (req: Request, res: Response) => {
  try {
    const { userId } = req.params;

    // Verify user can access these preferences
    if (req.user?.id !== userId && req.user?.role !== 'admin') {
      return res.status(403).json({
        success: false,
        error: 'Access denied'
      });
    }

    const preferences = await preferenceService.getUserPreferences(userId);

    if (!preferences) {
      return res.status(404).json({
        success: false,
        error: 'User preferences not found'
      });
    }

    res.json({
      success: true,
      preferences
    });

  } catch (error) {
    console.error('Get preferences error:', error);
    res.status(500).json({
      success: false,
      error: 'Internal server error'
    });
  }
});

/**
 * @route PUT /api/email/preferences/:userId
 * @desc Update user email preferences
 * @access Private
 */
router.put('/preferences/:userId', authMiddleware, async (req: Request, res: Response) => {
  try {
    const { userId } = req.params;
    const preferences = req.body;

    // Verify user can update these preferences
    if (req.user?.id !== userId && req.user?.role !== 'admin') {
      return res.status(403).json({
        success: false,
        error: 'Access denied'
      });
    }

    const result = await preferenceService.updateUserPreferences(
      userId,
      preferences,
      'user_dashboard',
      {
        ipAddress: req.ip,
        userAgent: req.get('User-Agent')
      }
    );

    if (result.success) {
      // Send preference update confirmation
      await emailOrchestrator.sendImmediateEmail(
        userId,
        'preference_update',
        { preferences },
        { priority: 'normal' }
      );
    }

    res.json(result);

  } catch (error) {
    console.error('Update preferences error:', error);
    res.status(500).json({
      success: false,
      error: 'Internal server error'
    });
  }
});

/**
 * @route POST /api/email/send-immediate
 * @desc Send immediate email to user
 * @access Private (Admin only)
 */
router.post('/send-immediate', authMiddleware, async (req: Request, res: Response) => {
  try {
    if (req.user?.role !== 'admin') {
      return res.status(403).json({
        success: false,
        error: 'Admin access required'
      });
    }

    const { userId, templateType, templateData, options } = req.body;

    if (!userId || !templateType) {
      return res.status(400).json({
        success: false,
        error: 'userId and templateType are required'
      });
    }

    const result = await emailOrchestrator.sendImmediateEmail(
      userId,
      templateType,
      templateData,
      options
    );

    res.json(result);

  } catch (error) {
    console.error('Send immediate email error:', error);
    res.status(500).json({
      success: false,
      error: 'Internal server error'
    });
  }
});

/**
 * @route POST /api/email/send-bulk
 * @desc Send bulk emails
 * @access Private (Admin only)
 */
router.post('/send-bulk', authMiddleware, async (req: Request, res: Response) => {
  try {
    if (req.user?.role !== 'admin') {
      return res.status(403).json({
        success: false,
        error: 'Admin access required'
      });
    }

    const { emails, options } = req.body;

    if (!Array.isArray(emails) || emails.length === 0) {
      return res.status(400).json({
        success: false,
        error: 'emails array is required and must not be empty'
      });
    }

    const result = await emailOrchestrator.sendBulkEmails(emails, options);

    res.json(result);

  } catch (error) {
    console.error('Send bulk emails error:', error);
    res.status(500).json({
      success: false,
      error: 'Internal server error'
    });
  }
});

/**
 * @route GET /api/email/track/open/:token.png
 * @desc Track email open (1x1 pixel)
 * @access Public
 */
router.get('/track/open/:token.png', async (req: Request, res: Response) => {
  try {
    const { token } = req.params;
    const cleanToken = token.replace('.png', '');

    // Track the open event
    await trackingService.trackEmailOpen(
      cleanToken,
      req.get('User-Agent'),
      req.ip
    );

    // Return 1x1 transparent pixel
    const pixel = Buffer.from(
      'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==',
      'base64'
    );

    res.writeHead(200, {
      'Content-Type': 'image/png',
      'Content-Length': pixel.length,
      'Cache-Control': 'no-cache, no-store, must-revalidate',
      'Pragma': 'no-cache',
      'Expires': '0'
    });
    
    res.end(pixel);

  } catch (error) {
    console.error('Track open error:', error);
    // Still return pixel even if tracking fails
    const pixel = Buffer.from(
      'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==',
      'base64'
    );
    res.writeHead(200, {
      'Content-Type': 'image/png',
      'Content-Length': pixel.length
    });
    res.end(pixel);
  }
});

/**
 * @route GET /api/email/track/click/:token
 * @desc Track email link click and redirect
 * @access Public
 */
router.get('/track/click/:token', async (req: Request, res: Response) => {
  try {
    const { token } = req.params;

    // Track the click event and get original URL
    const originalUrl = await trackingService.trackEmailClick(
      token,
      req.get('User-Agent'),
      req.ip,
      req.get('Referer')
    );

    if (originalUrl) {
      res.redirect(302, originalUrl);
    } else {
      res.redirect(302, emailConfig.system.baseUrl);
    }

  } catch (error) {
    console.error('Track click error:', error);
    res.redirect(302, emailConfig.system.baseUrl);
  }
});

/**
 * @route GET /api/email/analytics
 * @desc Get email analytics
 * @access Private (Admin only)
 */
router.get('/analytics', authMiddleware, async (req: Request, res: Response) => {
  try {
    if (req.user?.role !== 'admin') {
      return res.status(403).json({
        success: false,
        error: 'Admin access required'
      });
    }

    const { startDate, endDate, userId } = req.query;

    const start = startDate ? new Date(startDate as string) : new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
    const end = endDate ? new Date(endDate as string) : new Date();

    const analytics = await emailOrchestrator.getEmailAnalytics(
      start,
      end,
      userId as string
    );

    res.json({
      success: true,
      analytics
    });

  } catch (error) {
    console.error('Get analytics error:', error);
    res.status(500).json({
      success: false,
      error: 'Internal server error'
    });
  }
});

/**
 * @route GET /api/email/status
 * @desc Get email system status
 * @access Private (Admin only)
 */
router.get('/status', authMiddleware, async (req: Request, res: Response) => {
  try {
    if (req.user?.role !== 'admin') {
      return res.status(403).json({
        success: false,
        error: 'Admin access required'
      });
    }

    const status = await emailOrchestrator.getSystemStatus();

    res.json({
      success: true,
      status
    });

  } catch (error) {
    console.error('Get status error:', error);
    res.status(500).json({
      success: false,
      error: 'Internal server error'
    });
  }
});

/**
 * @route POST /api/email/webhook
 * @desc Handle email provider webhooks
 * @access Public (with signature verification)
 */
router.post('/webhook', async (req: Request, res: Response) => {
  try {
    // Verify webhook signature (implementation depends on provider)
    const signature = req.get('X-Signature') || req.get('X-Mailgun-Signature');
    
    // TODO: Implement signature verification for your email provider
    
    const { event, data } = req.body;

    const result = await emailOrchestrator.handleWebhookEvent(event, data);

    res.json(result);

  } catch (error) {
    console.error('Webhook error:', error);
    res.status(500).json({
      success: false,
      error: 'Webhook processing failed'
    });
  }
});

/**
 * @route POST /api/email/gdpr-request
 * @desc Handle GDPR data subject requests
 * @access Public
 */
router.post('/gdpr-request', async (req: Request, res: Response) => {
  try {
    const { userId, requestType, requesterEmail, requestDetails } = req.body;

    if (!userId || !requestType || !requesterEmail) {
      return res.status(400).json({
        success: false,
        error: 'userId, requestType, and requesterEmail are required'
      });
    }

    const result = await complianceService.handleGDPRRequest(
      userId,
      requestType,
      requesterEmail,
      requestDetails
    );

    res.json({
      success: result.success,
      message: result.success 
        ? `GDPR ${requestType} request submitted successfully. Request ID: ${result.requestId}`
        : result.error,
      requestId: result.requestId
    });

  } catch (error) {
    console.error('GDPR request error:', error);
    res.status(500).json({
      success: false,
      error: 'Internal server error'
    });
  }
});

// Graceful shutdown
process.on('SIGTERM', async () => {
  console.log('SIGTERM received, shutting down email system gracefully');
  try {
    await emailOrchestrator.stop();
    process.exit(0);
  } catch (error) {
    console.error('Error during shutdown:', error);
    process.exit(1);
  }
});

process.on('SIGINT', async () => {
  console.log('SIGINT received, shutting down email system gracefully');
  try {
    await emailOrchestrator.stop();
    process.exit(0);
  } catch (error) {
    console.error('Error during shutdown:', error);
    process.exit(1);
  }
});

export default router;